package net.example.manager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import com.oraycn.esframework.common.TransferingProject;
import com.oraycn.esframework.core.ClientType;
import com.oraycn.esframework.core.ContactsEventListener;
import com.oraycn.esframework.core.FileEventListener;
import com.oraycn.esframework.core.IRapidPassiveEngine;
import com.oraycn.esframeworkboost.networkdisk.Comment4NDisk;
import com.oraycn.esframeworkboost.networkdisk.NDiskParameters;
import com.oraycn.esframeworkboost.networkdisk.Passive.NDiskOutter;
import com.oraycn.omcs.MultimediaManagerFactory;
import com.oraycn.omcs.utils.BufferUtils;
import com.oraycn.esbasic.helpers.StringHelper;

import net.example.activity.LoginActivity;
import net.example.activity.MainActivity;
import net.example.activity.SplashActivity;
import net.example.activity.UserDetailActivity;
import net.example.model.AddFriendResult;
import net.example.model.BasicResult;
import net.example.model.ChangeMyPhoneResult;
import net.example.model.ChangePasswordResult;
import net.example.model.ChatInfo;
import net.example.model.CreateGroupResult;
import net.example.model.FileTransferUseType;
import net.example.model.GroupBan;
import net.example.model.GroupChangedType;
import net.example.model.GroupType;
import net.example.model.ResetPasswordResult;
import net.example.model.SnapchatMessage;
import net.example.model.SnapchatMessageRead;
import net.example.model.common.ChatBoxElemnetType;
import net.example.model.common.MessageFont;
import net.example.model.common.NonText;
import net.example.model.contract.AddFriendContract;
import net.example.model.contract.ChangeCommentNameContract;
import net.example.model.contract.ChangeGroupInfoContract;
import net.example.model.contract.ChangeGroupMembersContract;
import net.example.model.contract.ChangeHeadImageContract;
import net.example.model.contract.ChangePasswordContract;
import net.example.model.contract.ChangeUserBaseInfoContract;
import net.example.model.contract.CreateGroupContract;
import net.example.model.contract.GetAddFriend_GroupPageContract;
import net.example.model.contract.GroupBan4UserContract;
import net.example.model.contract.HandleAddFriendRequestContract;
import net.example.model.contract.HandleAddGroupRequestContract;
import net.example.model.contract.ManageGroupMembersNotifyContract;
import net.example.model.contract.MoveFriendToOtherCatalogContract;
import net.example.model.contract.RemoveGroupBan4UserContract;
import net.example.model.contract.RequestAddFriendContract;
import net.example.model.contract.RequestAddGroupContract;
import net.example.model.contract.ResetPasswordContract;
import net.example.model.event.FriendAddedNotifyEvent;
import net.example.model.event.FriendCatalogChangedEvent;
import net.example.model.event.ChatEvent;
import net.example.model.ContractType;
import net.example.model.event.FileEvent;
import net.example.model.FileMessage;
import net.example.model.event.FriendCommentNameChangedEvent;
import net.example.model.event.GroupBan4GroupEvent;
import net.example.model.event.GroupInfoChangedEvent;
import net.example.model.event.GroupUserChangedEvent;
import net.example.model.event.GroupDeletedNotifyEvent;
import net.example.model.event.MyPhoneChangedEvent;
import net.example.model.event.RemoveGroupBan4GroupEvent;
import net.example.model.event.SnapchatMessageReadEvent;
import net.example.model.event.SystemChatEvent;
import net.example.model.event.UserEvent;
import net.example.model.common.RichChatMessage;
import net.example.model.CommunicateMediaType;
import net.example.model.CommunicateType;
import net.example.model.contract.MediaCommunicateContract;
import net.example.model.GGGroup;
import net.example.model.GGUser;
import net.example.model.UserStatus;
import net.example.model.event.UserInfoChangedEvent;
import net.example.ggtalk.R;
import net.example.utils.Comment4OfflineFile;
import net.example.utils.CommonHelper;
import net.example.utils.CommonOptions;
import net.example.utils.LogHelper;
import net.example.utils.ToastUtils;
import net.example.utils.android.AndroidUtil;
import net.example.utils.android.IntentUtils;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import de.greenrobot.event.EventBus;
import io.netty.buffer.ByteBuf;

/**
 * Created by Jason Hong on 2019/5/28.
 */
public class Manager {
    private NDiskOutter nDiskOutter;
    public NDiskOutter getNDiskOutter()
    {
        return this.nDiskOutter;
    }

    public static Manager getInstance() {
        return Manager.SingletonHolder.instance;
    }
    private Context mContext= GGApplication.getInstance().getApplicationContext();

    //请求离线消息。。。
    public void requestMyOfflineMessage() {
        if (!this.engine.connected()) {
            ToastUtils.showShort(GGApplication.getInstance().getBaseContext(), this.mContext.getString(R.string.offlineTips));
            return;
        }
        this.engine.getCustomizeOutter().send(ContractType.GetOfflineMessage.getType(), null);
        this.engine.getCustomizeOutter().send(ContractType.GetOfflineFile.getType(),null);
        this.engine.getCustomizeOutter().send(ContractType.GetGroupOfflineMessage.getType(),null);
    }

    //退出系统
    public void logout() {
        ClientGlobalCache.getInstance().getRapidPassiveEngine().close();
        MultimediaManagerFactory.GetSingleton().close();
        ClientGlobalCache.getInstance().clearCache();
        SharedPreferences sp = mContext.getSharedPreferences("logout", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.putBoolean("isLogout",true);
        editor.commit();
        Intent  intent = new Intent(mContext, LoginActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK );
        mContext.startActivity(intent);
    }

    /**
     * 发送系统消息（只是客户端自己的聊天框显示）
     * */
    public void sendSystemMessage(String senderID,String msg,boolean isGroupChat )
    {
        ChatEvent systemMessageEvent = new SystemChatEvent(senderID, msg,isGroupChat);
        EventBus.getDefault().post(systemMessageEvent);
    }

    public boolean sendChatMessage(String targetUserID,  RichChatMessage message) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(GGApplication.getInstance().getBaseContext(), this.mContext.getString(R.string.offlineTips));
            return false;
        }
        byte[] msg = null;
        try {
            msg = message.serialize();
        } catch (Exception ee) {
            ee.printStackTrace();
            return false;
        }
        this.engine.sendMessage(null, ContractType.CHAT.getType(), msg, targetUserID,2048,true);
        return true;
    }

    //转发消息 accepters 为GGUser、GGGroup 的ID
    public void sendChatMessage(final List<String> accepters, final ChatInfo chatInfo)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        if(accepters == null || accepters.size() == 0)
        {
            return;
        }
        try {
            //使用Tag携带 接收者的ID
            String ids = StringHelper.ContactString(accepters,",");
            RichChatMessage richChatMessage=chatInfo.getRichChatMessage();
            this.engine.sendMessage(null, ContractType.ChatTransfered.getType(),  richChatMessage.serialize(), ids,2048, true);

            for(String userID :accepters)
            {
                richChatMessage.TransferTime = new Date();
                ChatEvent chatEvent = new ChatEvent(userID, ClientType.ANDROID, this.engine.getCurrentUserID(), richChatMessage, userID.contains("*"));
                chatEvent.isEcho = true;
                chatEvent.ImageUrl=chatInfo.getImageUrl();
                EventBus.getDefault().post(chatEvent);
            }
        }catch (Exception ee) {
            ee.printStackTrace();
        }
    }

    //region 阅后自焚
    /**
     * 发送阅后即焚消息
     * */
    public boolean sendSnapchatMessage(String destUserID, SnapchatMessage snapchatMessage) {
        try {
            if (!this.engine.connected()) {
                ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
                return false;
            }
            //使用Tag携带 接收者的ID
            this.engine.sendMessage(null, ContractType.Snapchat.getType(), snapchatMessage.serialize(), destUserID, 2048, false);
            return true;

        } catch (Exception ee) {
            ee.printStackTrace();
            return false;
        }
    }

    /**
     * 发送已阅读了自焚消息
     * */
    public void sendSnapchatReadMessage(SnapchatMessage snapchatMessage)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        if (snapchatMessage == null)
        {
            return;
        }
        try {
            SnapchatMessageRead snapchatMessageRead=new SnapchatMessageRead(snapchatMessage.CreatorID,snapchatMessage.ID);

          //  this.engine.sendMessage(snapchatMessage.CreatorID,ContractType.SnapchatRead.getType(),snapchatMessage.serialize(),null,true);
          this.engine.sendMessage(snapchatMessage.CreatorID, ContractType.SnapchatRead.getType(), snapchatMessageRead.serialize(), null, 2048, true);
        }catch (Exception ee) {
            ee.printStackTrace();
        }
    }

    /**
     * 收到阅后即焚消息
     * */
    public void onSnapchatMessageReceived(String senderID,ClientType clientType, SnapchatMessage snapchatMessage)
    {
        boolean isEcho=this.engine.getCurrentUserID().equals(senderID);
        this.postChatEvent4RichChatMessageReceived(senderID,clientType,senderID,snapchatMessage.ChatBoxContent,false,isEcho,"",snapchatMessage.GetUniqueID());
    }

    /**
     * 收到对方已阅读了即焚消息
     * */
    public void onSnapchatReadReceived(String destUserID,SnapchatMessageRead snapchatMessageRead) {
        //  String destUserID = sourceUserID == ClientGlobalCache.getInstance().getCurrentUser().getUserID() ? snapchatMessageRead.SourceCreatorID : sourceUserID;
        String uniqueID = snapchatMessageRead.SourceCreatorID + '-' + snapchatMessageRead.MessageID;
        ClientGlobalCache.getInstance().DeleteChatMessageRecordInLocalDB4SnapchatMessageID(destUserID, uniqueID);
        EventBus.getDefault().post(new SnapchatMessageReadEvent(uniqueID, snapchatMessageRead.SourceCreatorID, destUserID));
    }
    //endregion

    private void insertChatMessageRecord(List<String> accepters,RichChatMessage richChatMessage)
    {
        for(String userID :accepters)
        {
            richChatMessage.TransferTime = new Date();
            ChatEvent chatEvent = new ChatEvent(userID, ClientType.ANDROID, this.engine.getCurrentUserID(), richChatMessage, userID.contains("*"));
            chatEvent.isEcho = true;
            EventBus.getDefault().post(chatEvent);
        }
    }

    public void acceptFile(String projectID, String savePath) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
//        File path = new File(savePath);
//        if( !path.exists()) {
//            path.mkdirs();
//        }
        engine.getFileOutter().beginReceiveFile(projectID, savePath);
    }

    public void cancelTransfering(String projectID) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        engine.getFileOutter().cancelTransfering(projectID);
        FileEvent event = new FileEvent(FileEvent.CANCEL_TRANSFERING);
        event.ProjectId = projectID;
        EventBus.getDefault().post(event);
    }

    public String sendFile(String target, String filePath) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return "";
        }
        if (ClientGlobalCache.getInstance().getUser(target).getUserStatus() == UserStatus.OffLine || target.equals(GGApplication.getInstance().TALKINGUSER)) {
            return this.sendOfflineFile(target, filePath);
        }
        return engine.getFileOutter().beginSendFile(target, filePath, "");
    }

    private String sendOfflineFile(String target, String filePath) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return "";
        }
        return  engine.getFileOutter().beginSendFile(null, filePath, Comment4OfflineFile.BuildComment(target,ClientType.ANDROID));
    }

    /**
     * 发送群聊天
     * @param groupId 群ID
     * @param message 消息体
     * @param tag 需要@的成员
     * */
    public boolean broadcastGroupChat(String groupId,  RichChatMessage message,String tag) {

        try {
            byte[] msg = message.serialize();
            broadcastMessage(groupId, msg,tag);
            return true;
        } catch (Exception ee) {
            ee.printStackTrace();
            return false;
        }
    }

    /**
     * 广播群消息
     * */
    public void broadcastMessage(String groupId, byte[] content,String tag) {
        try {
            if (!this.engine.connected()) {
                ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
                return;
            }
            engine.getContactsOutter().broadcastBlob(groupId, ContractType.GroupChat.getType(), content, tag, 20480);
        } catch (Exception ee) {
            ee.printStackTrace();
        }
    }

    //根据讨论组ID获取组成员
    public List<GGUser> getGGUserByGroupID(String groupID)
    {
        GGGroup GGGroup = ClientGlobalCache.getInstance().getGroup(groupID);
        if(GGGroup ==null)
        {
            return new ArrayList<GGUser>();
        }
        if(GGGroup.getChildCount()==0)
        {
            return new ArrayList<GGUser>();
        }
        String members = GGGroup.getMembers();
        String[] memeberArray = members.split(",");
        return ClientGlobalCache.getInstance().getGGUserList(Arrays.asList(memeberArray));
    }

    private static class SingletonHolder {
        public static Manager instance = new Manager();
    }

    private IRapidPassiveEngine engine;

    public void init(IRapidPassiveEngine engine) {
        this.engine = engine;
        this.nDiskOutter=new NDiskOutter(engine.getFileOutter(),engine.getCustomizeOutter());
        ClientGlobalCache.getInstance().getCurrentUser().Phone = this.getPhone4UserID(this.engine.getCurrentUserID());
        setFileListener();
        setContactsListener();
    }

    private void setContactsListener() {
        engine.getContactsOutter().setContactsEventListener(new ContactsEventListener() {

            @Override
            public void contactsDeviceConnected(String userID, ClientType clientType) {
            }

            @Override
            public void contactsDeviceDisconnected(String userID, ClientType clientType) {
            }

            @Override
            public void contactsOffline(String userID) {
                Log.i("ContactsManager", "contactsOffline:" + userID);
                //掉线更新状态
                ClientGlobalCache.getInstance().onUserStatusChanged(userID, UserStatus.OffLine);
                EventBus.getDefault().post(new UserEvent(userID, UserStatus.OffLine));
            }

            @Override
            public void broadcastReceived(String broadcasterID, ClientType clientType, String groupID, int broadcastType, byte[] bytes,String tag) {
                    try {
                        if(clientType== ClientType.ANDROID && broadcasterID.equals(GGApplication.getInstance().getCurrentUser().getUserID())){
                            return;
                        }
                        switch (ContractType.getContractTypeByCode(broadcastType))
                        {
                            case GroupChat:
                            {
                                if (broadcasterID == null || broadcasterID.equals("_0"))
                                {
                                    broadcasterID = tag;
                                    if(broadcasterID.equals(GGApplication.getInstance().getCurrentUser().getUserID())){
                                        return;
                                    }
                                }
                                RichChatMessage chatMsg = new RichChatMessage();
                                chatMsg.deserialize(BufferUtils.wrappedBuffer(bytes));
                                postChatEvent4RichChatMessageReceived(groupID, clientType, broadcasterID, chatMsg, true, broadcasterID.equals(engine.getCurrentUserID()), tag, "");
                                if (AndroidUtil.isAppIsInBackground(GGApplication.applicationContext)) {
                                    Intent intent=new Intent(GGApplication.applicationContext, SplashActivity.class);
                                    intent.putExtra("TalkingUserID", groupID);
                                    intent.putExtra("isGroup", true);
                                    String serderName = ClientGlobalCache.getInstance().getGroup(groupID).getName();
                                    PendingIntent pendingIntent = PendingIntent.getActivity(GGApplication.applicationContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
                                    AndroidUtil.showNotifyMessage(GGApplication.applicationContext, pendingIntent, serderName, chatMsg.getText(), ClientGlobalCache.getInstance().getTotalNotReadMsgCount());
                                } else {
                                    GGApplication.getInstance().ringForMessage();
                                }
                                break;
                            }
                            case SomeoneQuitGroup:{
                                String userID = new String(bytes, StandardCharsets.UTF_8);
                                ClientGlobalCache.getInstance().onSomeoneQuitGroup(groupID,userID);
                                List<String> userIDs=new ArrayList<>();
                                userIDs.add(userID);
                                EventBus.getDefault().post(new GroupUserChangedEvent(groupID, GroupChangedType.SomeoneQuit,userID, userIDs));
                                break;
                            }
                            case SomeoneJoinGroup:{
                                String userID = new String(bytes, StandardCharsets.UTF_8);
                                ClientGlobalCache.getInstance().onSomeoneJoinGroup(groupID,userID);
                                List<String> userIDs=new ArrayList<>();
                                userIDs.add(userID);
                                EventBus.getDefault().post(new GroupUserChangedEvent(groupID, GroupChangedType.SomeoneJoin,userID, userIDs));
                                break;
                            }
                            case PulledIntoGroupNotify:{
                                ManageGroupMembersNotifyContract contract=new ManageGroupMembersNotifyContract();
                                contract.deserialize(bytes);
                                ClientGlobalCache.getInstance().OnUsersPulledIntoGroup(groupID,contract.OperatorID,contract.GuestList);
                                if (contract.GuestList.contains(engine.getCurrentUserID())) {
                                    EventBus.getDefault().post(new GroupUserChangedEvent(groupID, GroupChangedType.MyselfBePulledIntoGroup, contract.OperatorID,contract.GuestList));
                                } else {
                                    EventBus.getDefault().post(new GroupUserChangedEvent(groupID, GroupChangedType.OtherBePulledIntoGroup, contract.OperatorID,contract.GuestList));
                                }
                                break;
                            }
                            case RemovedFromGroupNotify:
                                ManageGroupMembersNotifyContract contract=new ManageGroupMembersNotifyContract();
                                contract.deserialize(bytes);
                                ClientGlobalCache.getInstance().OnUsersRemoveOutGroup(groupID,contract.OperatorID,contract.GuestList);
                                if (contract.GuestList.contains(engine.getCurrentUserID())) {
                                    EventBus.getDefault().post(new GroupUserChangedEvent(groupID, GroupChangedType.MyselfBeRemovedFromGroup, contract.OperatorID,contract.GuestList));
                                    ClientGlobalCache.getInstance().removeGroup(groupID);
                                    ClientGlobalCache.getInstance().DeleteChatMessageRecordInLocalDB(groupID,true);
                                    EventBus.getDefault().post(new GroupDeletedNotifyEvent(groupID, false));
                                } else {
                                    EventBus.getDefault().post(new GroupUserChangedEvent(groupID, GroupChangedType.OtherBeRemovedFromGroup, contract.OperatorID,contract.GuestList));
                                }
                                break;
                            case GroupDeleted:{
                                ClientGlobalCache.getInstance().removeGroup(groupID);
                                ClientGlobalCache.getInstance().DeleteChatMessageRecordInLocalDB(groupID,true);
                                EventBus.getDefault().post(new GroupDeletedNotifyEvent(groupID, false));
                                break;
                            }
                            case GroupInfoChanged:
                                ChangeGroupInfoContract changeGroupInfoContract=new ChangeGroupInfoContract();
                                changeGroupInfoContract.deSerialize(bytes);
                                GGGroup group = ClientGlobalCache.getInstance().getGroup(groupID);
                                group.setName(changeGroupInfoContract.GroupName);
                                group.setAnnounce(changeGroupInfoContract.Announce);
                                ClientGlobalCache.getInstance().OnCreateOrUpdateGroup(group);
                                EventBus.getDefault().post(new GroupInfoChangedEvent(changeGroupInfoContract.OperatorID,changeGroupInfoContract.GroupID,changeGroupInfoContract.GroupName,changeGroupInfoContract.Announce));
                                break;
                            case GroupBan4Group:
                                String operatorID=tag;
                                EventBus.getDefault().post(new GroupBan4GroupEvent(groupID,operatorID));
                                // tag-operatorID, groupID
                                // TO DO 全员禁言
                                break;
                            case RemoveGroupBan4Group:
                                // TO DO 解除全员禁言
                                EventBus.getDefault().post(new RemoveGroupBan4GroupEvent(groupID));
                            break;
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
            }


        });
    }

    private void setFileListener() {
        engine.getFileOutter().setFileEventListener(new FileEventListener() {
            @Override
            public void fileRequestReceived(TransferingProject transferingProject) {
                if (transferingProject != null) {
                    String comment= transferingProject.getComment();
                    NDiskParameters nDiskParameters= Comment4NDisk.Parse(comment);
                    if(nDiskParameters!=null)
                    {
                        String saveDirectoryPath =nDiskParameters.DirectoryPath.substring(0,nDiskParameters.DirectoryPath.lastIndexOf("/")+1);
                        acceptFile(transferingProject.getProjectId(), saveDirectoryPath);//同意接收文件
                        return;
                    }

                    String offlineFileSenderID=Comment4OfflineFile.ParseUserID(comment);
                    Boolean offlineFile= (offlineFileSenderID !=null);
                    if(offlineFile)
                    {
                        if(offlineFileSenderID.equals(engine.getCurrentUserID()))
                        {
                            if(Comment4OfflineFile.ParseClientType(comment) == ClientType.ANDROID.getType())
                            {
                                return;
                            }
                        }
                    }
                    String senderID=offlineFile?offlineFileSenderID:transferingProject.getSender();
                    FileEvent event = new FileEvent(FileEvent.FILE_REQ);
                    event.ProjectId = transferingProject.getProjectId();
                    event.FileSize = transferingProject.getFileSize();
                    event.TransferSize = (int) transferingProject.getTransferSize();
                    event.Accpet = false;
                    event.Sender = senderID;
                    event.FileName = transferingProject.getFileName();
                    event.FilePath =transferingProject.getLocalSavePath();
                    event.FileTransferUseType= CommonHelper.getFileTransferUseType(transferingProject);
                    event.TransferingProject=transferingProject;
                    EventBus.getDefault().post(event);
                    if(event.FileTransferUseType== FileTransferUseType.Comment4NDisk){return;}

                    FileMessage fileMsg = new FileMessage(transferingProject.getLocalSavePath(), event.FileName, (int) event.FileSize, event.TransferSize, event.ProjectId);
                    //这个是给会话用的

                    ChatEvent chatEvent = new ChatEvent(senderID, transferingProject.getDestClientType(), senderID, fileMsg, false);
                    if(senderID.equals(engine.getCurrentUserID()))
                    {
                        chatEvent.isEcho=true;
                    }
                    EventBus.getDefault().post(chatEvent);
                    GGApplication.getInstance().ringForMessage();
                }
            }

            @Override
            public void fileResponseReceived(TransferingProject project, boolean accept) {
                if(project!=null) {
                    FileEvent event = new FileEvent(FileEvent.FILE_RESP, accept);
                    event.ProjectId = project.getProjectId();
                    event.FileSize = project.getFileSize();
                    event.TransferSize = (int) project.getTransferSize();
                    event.Sender = project.getSender();
                    event.FileName = project.getFileName();
                    event.FileTransferUseType = CommonHelper.getFileTransferUseType(project);
                    event.TransferingProject=project;
                    EventBus.getDefault().post(event);
                }
            }

            @Override
            public void fileTransStarted(TransferingProject project) {
                if(project==null){return;}
                FileEvent event = new FileEvent(FileEvent.FILE_START);
                event.ProjectId = project.getProjectId();
                event.FileTransferUseType = CommonHelper.getFileTransferUseType(project);
                event.TransferingProject = project;
                event.FileName=project.getFileName();
                event.Common=project.getComment();
                EventBus.getDefault().post(event);
            }

            @Override
            public void fileResumedTransStarted(TransferingProject project) {
                if(project==null){return;}
                FileEvent event = new FileEvent(FileEvent.FILE_START);
                event.ProjectId = project.getProjectId();
                event.FileTransferUseType = CommonHelper.getFileTransferUseType(project);
                event.TransferingProject = project;
                event.FileName=project.getFileName();
                event.Common=project.getComment();
                EventBus.getDefault().post(event);
            }

            @Override
            public void fileSendedProgress(String projectId, long totlaSize, long transfered) {
                TransferingProject project = engine.getFileOutter().getTransferingProject(projectId);
                if(project==null){
                    return;
                }
                FileEvent event = new FileEvent(FileEvent.FILE_PROCESS);
                event.ProjectId = projectId;
                event.FileSize = (int) totlaSize;
                event.TransferSize = (int) transfered;
                event.Accpet =true;
                event.FileTransferUseType= CommonHelper.getFileTransferUseType(project);
                event.TransferingProject = project;
                EventBus.getDefault().post(event);
            }

            @Override
            public void fileTransDisruptted(String projectId, FileTransDisrupttedType disrupttedType, String cause) {
                TransferingProject project = engine.getFileOutter().getTransferingProject(projectId);
                if(project==null){
                    return;
                }
                FileEvent event = new FileEvent(FileEvent.FILE_TRANS_DISRUPPTTED);
                event.ProjectId = projectId;
                event.DisrupttedType = disrupttedType;
                event.Cause = cause;
                event.Accpet =false;
                event.FileTransferUseType= CommonHelper.getFileTransferUseType(project);
                event.TransferingProject = project;
                if(disrupttedType==FileTransDisrupttedType.DestCancel||disrupttedType==FileTransDisrupttedType.ActiveCancel)
                {
                    event.Type=FileEvent.CANCEL_TRANSFERING;
                }
                EventBus.getDefault().post(event);
            }

            @Override
            public void fileTransCompleted(String projectId) {
                TransferingProject project = engine.getFileOutter().getTransferingProject(projectId);
                if(project==null){
                    return;
                }
                FileEvent event = new FileEvent(FileEvent.FILE_COMPLETED);
                event.ProjectId = projectId;
                event.Accpet =true;
                event.FileTransferUseType= CommonHelper.getFileTransferUseType(project);
                event.TransferingProject = project;
                EventBus.getDefault().post(event);
            }
        });
    }


    public void sendMediaCommunicate(String destUserID, CommunicateMediaType mediaType, CommunicateType communicateType, String tag,  int destClientType) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        MediaCommunicateContract contract = new MediaCommunicateContract(mediaType, communicateType, tag, destClientType);
        byte[] bytes = null;
        try {
            bytes = contract.toBytes();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(communicateType ==CommunicateType.Request){
            //请求消息发送到服务端，服务端中转 （若对方不在线则会推送消息）
            engine.sendMessage(null, ContractType.MediaCommunicate.getType(), bytes,destUserID,false);
        }else {
            engine.sendMessage(destUserID, ContractType.MediaCommunicate.getType(), bytes, tag, true);
        }

        //设置全局通话对象
        if (mediaType == CommunicateMediaType.Audio || mediaType == CommunicateMediaType.Video || mediaType == CommunicateMediaType.GroupVideo)
        {
            if (communicateType == CommunicateType.Agree || communicateType == CommunicateType.Request)
            {
                destUserID = mediaType == CommunicateMediaType.GroupVideo ? tag : destUserID;
                CommonOptions.CallingID4VideoOrVoice = destUserID;
            }
            else
            {
                CommonOptions.CallingID4VideoOrVoice = "";
            }
        }
    }

    /**
     * 向所有当前群聊组成员 发送拒绝群视频请求
     * */
    public void sendGroupVideoChat4Reject(String videoGroupID,String[] memberIDs,CommunicateType communicateType)
    {
        for (String id: memberIDs)
        {
            if(id.equals(ClientGlobalCache.getInstance().getCurrentUser().getUserID()))
            {continue;}
            Manager.getInstance().sendMediaCommunicate(id, CommunicateMediaType.GroupVideo, communicateType,videoGroupID,-1);
            LogHelper.i(id+"群拒绝已发送！");
        }
    }

    /**
     * 根据用户ID获取电话号码 null：获取失败
     * */
    public String getPhone4UserID(String userID)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return null;
        }
        try {
            byte[] bUser = this.engine.getCustomizeOutter().query(ContractType.GetUserPhone.getType(), userID.getBytes(StandardCharsets.UTF_8));
            if (bUser == null)
            {
                return null;
            }
            return new String(bUser, StandardCharsets.UTF_8);
        }catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 重置密码
     * */
    public ResetPasswordResult resetPassword(ResetPasswordContract contract)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return ResetPasswordResult.Error;
        }
        try {
            byte[] info = ClientGlobalCache.getInstance().getRapidPassiveEngine().getCustomizeOutter().query(ContractType.ResetPassword.getType(), contract.serialize());
            ByteBuf buf = BufferUtils.wrappedBuffer(info) ;
            return ResetPasswordResult.values()[buf.readInt()];
        }catch (Exception e)
        {
            e.printStackTrace();
        }
        return ResetPasswordResult.Error;
    }

    /// <summary>
    /// 修改密码。
    /// </summary>
    public ChangePasswordResult changeMyPassword(String oldPasswordMD5, String newPasswordMD5) {
        try {
            ChangePasswordContract contract = new ChangePasswordContract(oldPasswordMD5, newPasswordMD5);
            byte[] bRes = this.engine.getCustomizeOutter().query(ContractType.ChangePassword.getType(), contract.serialize());
            ByteBuf buf = BufferUtils.wrappedBuffer(bRes);
            return ChangePasswordResult.values()[buf.readInt()];
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ChangePasswordResult.Error;
    }

    public List<GGUser> doSearchUser(String idOrName) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return null;
        }
        try {
            byte[] date = this.engine.getCustomizeOutter().query(null, ContractType.SearchUser.getType(), idOrName.getBytes());
            List<GGUser> GGUsers = GGUser.deserializeUserList(date);
            return GGUsers;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    //region 更改自己的信息（名称、签名、状态、头像,电话号码）

    /**
     * 修改自己的电话号码 （个人信息的版本号一同更改）
     * */
    public ChangeMyPhoneResult changeMyPhone(String newPhone) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return ChangeMyPhoneResult.Error;
        }
        try {
            byte[] data = this.engine.getCustomizeOutter().query(ContractType.ChangeMyPhone.getType(), newPhone.getBytes(StandardCharsets.UTF_8));
            ByteBuf buf = BufferUtils.wrappedBuffer(data);
            ChangeMyPhoneResult result = ChangeMyPhoneResult.values()[buf.readInt()];
            if (result == ChangeMyPhoneResult.Succeed) {
                ClientGlobalCache.getInstance().getCurrentUser().Phone = newPhone;
                EventBus.getDefault().post(new MyPhoneChangedEvent(newPhone));
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return ChangeMyPhoneResult.Error;
        }
    }

    public void changeMyStatus(UserStatus status) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        if (status != null) {
            engine.getCustomizeOutter().send(ContractType.ChangeStatus.getType(), UserStatus.GetStatusBytes(status));
        }
    }

    public BasicResult changeMyBaseInfo(String name, String signature , String orgID)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return BasicResult.Error;
        }
        try {
            GGUser currentUser=ClientGlobalCache.getInstance().getCurrentUser();
            ChangeUserBaseInfoContract contract = new ChangeUserBaseInfoContract(currentUser.getUserID(), name, signature, orgID);
            this.engine.getCustomizeOutter().send(ContractType.ChangeMyBaseInfo.getType(),contract.serialize());
            this.engine.sendMessage(null,ContractType.ChangeMyBaseInfo.getType(),contract.serialize(),"",true);
            ClientGlobalCache.getInstance().updateUserBaseInfo(currentUser.getUserID(),name,signature,orgID,currentUser.getVersion());
            EventBus.getDefault().post(new UserInfoChangedEvent(currentUser.getUserID()));
            return BasicResult.Succeed;
        }catch (Exception ee) {
            ee.printStackTrace();
            return BasicResult.Error;
        }
    }

    public BasicResult changeMyHeadImage(int defaultHeadImageIndex, byte[] customizedHeadImage) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return BasicResult.Error;
        }
        try {
            ChangeHeadImageContract contract = new ChangeHeadImageContract(engine.getCurrentUserID(), defaultHeadImageIndex, customizedHeadImage);
            this.engine.sendMessage(null, ContractType.ChangeMyHeadImage.getType(), contract.serialize(), null, true);
            //更改缓存 直接从服务端拿最新的数据（主要是为了拿到圆形头像）
            GGUser GGUser = ClientGlobalCache.getInstance().DoGetUser(engine.getCurrentUserID());
            ClientGlobalCache.getInstance().getCurrentUser().updateHeadImage(GGUser.getHeadImageIndex(), GGUser.getHeadImageData());
            //EventBus.getDefault().post(new UserHeadImageChangedEvent(changHeadImageContract.UserID,changHeadImageContract.HeadImageIndex,changHeadImageContract.HeadImage));

            return BasicResult.Succeed;
        } catch (Exception ee) {
            ee.printStackTrace();
            return BasicResult.Error;
        }
    }
    //endregion

    //region 新增好友分组、移动至另一个分组、修改好友备注
    public BasicResult addFriendCatalog(String catalog)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return BasicResult.Error;
        }
        try {
            //this.engine.getCustomizeOutter().send(ContractType.AddFriendCatalog.getType(),catalog.getBytes("UTF-8"));
            this.engine.sendMessage(null,ContractType.AddFriendCatalog.getType(),catalog.getBytes(StandardCharsets.UTF_8),"",true);
            ClientGlobalCache.getInstance().getCurrentUser().AddFriendCatalog(catalog);
            EventBus.getDefault().post(new FriendCatalogChangedEvent());
            return BasicResult.Succeed;

        } catch (Exception ee) {
            ee.printStackTrace();
            return BasicResult.Error;
        }
    }

    /**
     * 自己是否在对方黑名单中
     * */
    public boolean isInHisBlackList(String destUserID)
    {
//        try {
//            byte[] res = this.engine.getCustomizeOutter().query(ContractType.InHisBlackList.getType(), destUserID.getBytes("UTF-8"));
//            ByteBuf buffer = SerializeHelper.wrappedBuffer(res);
//            return buffer.readBoolean();
//        }catch (Exception ex){
//            ex.printStackTrace();
//            return false;
//        }
        return false;
    }

    public BasicResult moveFriendCatalog(String friendID, String oldCatalog, String newCatalog)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return BasicResult.Error;
        }
        try {
            MoveFriendToOtherCatalogContract contract = new MoveFriendToOtherCatalogContract(friendID, oldCatalog, newCatalog);
//            this.engine.getCustomizeOutter().send(ContractType.MoveFriendToOtherCatalog.getType(),contract.serialize());
            this.engine.sendMessage(null,ContractType.MoveFriendToOtherCatalog.getType(),contract.serialize(),"",true);
            ClientGlobalCache.getInstance().getCurrentUser().moveFriend(friendID,oldCatalog,newCatalog);
            EventBus.getDefault().post(new FriendCatalogChangedEvent());
            return BasicResult.Succeed;
        }catch (Exception ee) {
            ee.printStackTrace();
            return BasicResult.Error;
        }
    }

    public BasicResult updateFriendCommentName(String friendID,String commentName)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return BasicResult.Error;
        }
        try {
            ChangeCommentNameContract contract = new ChangeCommentNameContract(friendID, commentName);
            this.engine.sendMessage(null,ContractType.ChangeUnitCommentName.getType(),contract.serialize(),null,true);
            ClientGlobalCache.getInstance().onChangeUnitCommentName(contract.UnitID, contract.CommentName);
            FriendCommentNameChangedEvent event=new FriendCommentNameChangedEvent(friendID,ClientGlobalCache.getInstance().getUser(friendID).getCommentName());
            EventBus.getDefault().post(event);
            return BasicResult.Succeed;
        }catch (Exception ee) {
            ee.printStackTrace();
            return BasicResult.Error;
        }
    }
    //endregion

    //region 好友（添加删除好友、申请加好友）

    /**
     * 删除好友
     * */
    public void removeFriend(String friendID)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        try {
//            this.engine.getCustomizeOutter().send(ContractType.RemoveFriend.getType(),friendID.getBytes("UTF-8")); 20210625 改为多端
            this.engine.sendMessage(null,ContractType.RemoveFriend.getType(),friendID.getBytes(StandardCharsets.UTF_8),null,true);
        }catch (Exception ee) {
            ee.printStackTrace();
        }
    }

    /**
     * 添加好友 （不需要对方验证）
     * */
    public AddFriendResult addFriend(String friendID, String catalogName)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return AddFriendResult.Error;
        }
        try {
            AddFriendContract contract = new AddFriendContract(friendID, catalogName);
            byte[] info = contract.serialize();
            byte[] bRes = this.engine.getCustomizeOutter().query(ContractType.AddFriend.getType(), info);
            ByteBuf buf = BufferUtils.wrappedBuffer(bRes) ;
            return AddFriendResult.values()[buf.readInt()];
        }catch (Exception ee) {
            ee.printStackTrace();
        }
        return AddFriendResult.Error;
    }

    /**
     * 申请添加好友
     * @param accepterID 接收者ID
     * @param comment 备注
     * @param requesterCatalogName 请求者好友分组
     * */
    public BasicResult requestAddFriend(String accepterID, String comment,String requesterCatalogName)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return BasicResult.Error;
        }
        try
        {
            RequestAddFriendContract contract = new RequestAddFriendContract(this.engine.getCurrentUserID(), accepterID, comment, requesterCatalogName);
            byte[] info = contract.serialize();
            this.engine.sendMessage(null, ContractType.RequestAddFriend.getType(), info, accepterID, true);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            return BasicResult.Error;
        }
        return BasicResult.Succeed;
    }

    /**
    * 处理添加好友请求
    *
    * @param requesterID 请求者ID
    * @param accepterCatalogName 接收者好友分组
    * @param agree 是否同意
     */
    public void handleAddFriendRequest(String requesterID, String accepterCatalogName, boolean agree)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        try
        {
            HandleAddFriendRequestContract contract = new HandleAddFriendRequestContract(requesterID, this.engine.getCurrentUserID(), accepterCatalogName, agree);
            byte[] info = contract.serialize();
            this.engine.sendMessage(null, ContractType.HandleAddFriendRequest.getType(), info, requesterID, true);
            if (agree)
            {
                GGUser friend = ClientGlobalCache.getInstance().getUser(requesterID);
                ClientGlobalCache.getInstance().addUser(friend);
                EventBus.getDefault().post(new FriendAddedNotifyEvent(friend,accepterCatalogName,true));
            }
        }catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }

    /**
    *发送获取申请好友记录。   服务端会返回一条GetAddFriendPage协议的消息。在OrayApplication中messageReceived接收到返回的结果
    */
    public void getAddFriendPage()
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        try {
            GetAddFriend_GroupPageContract contract=new GetAddFriend_GroupPageContract(this.engine.getCurrentUserID(),0,20);
            this.engine.sendMessage(null,ContractType.GetAddFriendPage.getType(),contract.serialize(),null,false);
        }catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
    //endregion

    //region 讨论组 （讨论组申请加入、创建、删除、人员变动）

    /**
     * 根据群名称或群id 精确查找群组
     * @param idOrName 群名称或ID  精确查找
     * */
    public List<GGGroup> searchGroupList(String idOrName)
    {
        try {
            byte[] datas = this.engine.getCustomizeOutter().query(ContractType.SearchGroup.getType(), idOrName.getBytes(StandardCharsets.UTF_8));
            return GGGroup.deserializeGroupList(datas);
        }catch (Exception ex)
        {
            ex.printStackTrace();
            return null;
        }

    }


    /**
     * 申请加入讨论组
     * @param groupID 组ID
     * @param comment 备注
     * */
    public BasicResult requestAddGroup(String groupID, String comment)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return BasicResult.Error;
        }
        try {
            RequestAddGroupContract contract = new RequestAddGroupContract(this.engine.getCurrentUserID(), groupID, comment);
            this.engine.sendMessage(null,ContractType.RequestAddGroup.getType(),contract.serialize(),null,true);

        } catch (Exception ex)
        {
            ex.printStackTrace();
            return BasicResult.Error;
        }
        return BasicResult.Succeed;
    }

    /**
     * 处理加入好友讨论组的请求
     * @param requesterID 请求者ID
     * @param groupID 组ID
     * @param agree 是否同意加入
     * */
    public void handleAddGroupRequest(String requesterID, String groupID, boolean agree)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        try {
            HandleAddGroupRequestContract contract = new HandleAddGroupRequestContract(requesterID, groupID, agree);
            this.engine.sendMessage(null, ContractType.HandleAddGroupRequest.getType(), contract.serialize(), requesterID, true);
        }catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }

    /**
     * 发送获取申请加入讨论组记录。   服务端会返回一条GetAddGroupPage协议的消息。在OrayApplication中messageReceived接收到返回的结果
     * */
    public void getAddGroupPage()
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        try {
            GetAddFriend_GroupPageContract contract = new GetAddFriend_GroupPageContract(this.engine.getCurrentUserID(), 0, 1000);
            this.engine.sendMessage(null, ContractType.GetAddGroupPage.getType(), contract.serialize(), null, false);
        }catch (Exception ee) {
            ee.printStackTrace();
        }
    }

    public CreateGroupResult CreateGroup(GroupType groupType , String groupID, String groupName, String announce, List<String> members,boolean isPrivate)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return CreateGroupResult.Error;
        }
        try {
            CreateGroupContract contract = new CreateGroupContract(groupType, groupID, groupName, announce, members,isPrivate);
            byte[] bRes = this.engine.getCustomizeOutter().query(ContractType.CreateGroup.getType(), contract.serialize());
            ByteBuf buf = BufferUtils.wrappedBuffer(bRes) ;
            CreateGroupResult res = CreateGroupResult.values()[buf.readInt()];
            if (res == CreateGroupResult.Succeed)
            {
                ClientGlobalCache.getInstance().reLoadCurrentUserFromServer();
                GGGroup group = new GGGroup(ClientGlobalCache.getInstance().getCurrentUser().getUserID(),GroupType.CommonGroup,groupID,groupName,announce,members,isPrivate);
                ClientGlobalCache.getInstance().OnCreateOrUpdateGroup(group);
//                EventBus.getDefault().post(new GroupCreatedEvent(group));
            }
            return res;
        }catch(Exception ee) {
            ee.printStackTrace();
        }
        return CreateGroupResult.Error;
    }

    public BasicResult ChangeGroupMembers(String groupID, List<String> members)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return BasicResult.Error;
        }
        try {
            GGGroup group = ClientGlobalCache.getInstance().getGroup(groupID);
            if (groupID == null)
            {
                return BasicResult.NotExisted;
            }
            List<String> groupMemberList=group.getChildMemberList();
            List<String> addedList=new ArrayList<>();
            List<String> removedList=new ArrayList<>();
            for (String userID : members)
            {
                if (!groupMemberList.contains(userID))
                {
                    addedList.add(userID);
                }
            }
            for (String userID : group.getChildMemberList())
            {
                if (!members.contains(userID))
                {
                    removedList.add(userID);
                }
            }
            ChangeGroupMembersContract contract = new ChangeGroupMembersContract(groupID, addedList, removedList);
            this.engine.getCustomizeOutter().send(ContractType.ChangeGroupMembers.getType(),contract.serialize());
            ///缓存在server发来消息中处理
            return BasicResult.Succeed;
        }catch(Exception ee) {
            ee.printStackTrace();
            return BasicResult.Error;
        }

    }

    public BasicResult changeGroupInfo(String groupID, String name, String announce)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return BasicResult.Error;
        }
        try {
            GGGroup group = ClientGlobalCache.getInstance().getGroup(groupID);
            if(groupID == null)
            {
                return BasicResult.NotExisted;
            }
            ChangeGroupInfoContract contract = new ChangeGroupInfoContract(ClientGlobalCache.getInstance().getCurrentUser().getUserID(), groupID, name, announce);
            this.engine.getCustomizeOutter().send(ContractType.ChangeGroupInfo.getType(), contract.serialize());
            group.setName(name);
            group.setAnnounce(announce);
            ClientGlobalCache.getInstance().OnCreateOrUpdateGroup(group);
            EventBus.getDefault().post(new GroupInfoChangedEvent(ClientGlobalCache.getInstance().getCurrentUser().getUserID(),groupID,name,announce));
            return BasicResult.Succeed;
        }catch(Exception ee) {
            ee.printStackTrace();
            return BasicResult.Error;
        }

    }

    //解散讨论组
    public void deleteGroup(String groupID) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        try {
//            this.engine.getCustomizeOutter().send(ContractType.DeleteGroup.getType(), groupID.getBytes("UTF-8"));//20210625 改为多端
            this.engine.sendMessage(null,ContractType.DeleteGroup.getType(), groupID.getBytes(StandardCharsets.UTF_8),null,true);
//            ClientGlobalCache.getInstance().removeGroup(groupID);会收到组删除GroupDeleted的广播通知，统一再通知中做处理
        } catch (Exception ee) {
            ee.printStackTrace();
        }
    }

    //退出讨论组
    public void quitGroup(String groupID)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        if (!this.engine.connected()) {
            ToastUtils.showShort(GGApplication.getInstance().getBaseContext(), "您已掉线！");
            return;
        }
        try {
//            this.engine.getCustomizeOutter().send(ContractType.QuitGroup.getType(),groupID.getBytes("UTF-8"));20210625 改为多端
            this.engine.sendMessage(null,ContractType.QuitGroup.getType(),groupID.getBytes(StandardCharsets.UTF_8),null,true);
            ClientGlobalCache.getInstance().removeGroup(groupID);
            EventBus.getDefault().post(new GroupDeletedNotifyEvent(groupID, true));
        }catch (Exception ee) {
            ee.printStackTrace();
        }
    }
    //endregion

    //region 跳转到用户详情页面（自己、其他人）
    /**
     * 跳转到用户详情页面
     */
    public void moveToUserDetail(Context context, String userID)
    {
        if(userID.equals(ClientGlobalCache.getInstance().getCurrentUser().getUserID()))
        {
            Intent intent = new Intent(context, MainActivity.class);
            intent.putExtra("tabID", R.id.btn_main_setting);
            context.startActivity(intent);
        }
        else
        {
            IntentUtils.startActivityForString(context, UserDetailActivity.class,"requestID",userID);
        }
    }
    //endregion

    //region 群禁言 （禁言成员个人、禁言全员）
    /**
     * 将群中具体成员设置禁言
     * @param groupID 群ID
     * @param destUserID 对方账号
     * @param comment 备注
     * @param minutes 禁言时长（单位：分钟）
     * */
    public void setGroupBan4User(String groupID, String destUserID, String comment, double minutes) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        if (minutes <= 0) {
            return;
        }
        try {
            GroupBan4UserContract contract = new GroupBan4UserContract(groupID, this.engine.getCurrentUserID(), destUserID, comment, minutes);
            this.engine.sendMessage(null, ContractType.GroupBan4User.getType(), contract.serialize(), null, true);
        } catch (Exception ee) {
            ee.printStackTrace();
        }
    }

    /**
     * 解除群中具体成员禁言
     * */
    public void removeGroupBan4User(String groupID, String destUserID)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        try {
            RemoveGroupBan4UserContract contract = new RemoveGroupBan4UserContract(groupID, destUserID);
            this.engine.sendMessage(null, ContractType.RemoveGroupBan4User.getType(), contract.serialize(), this.engine.getCurrentUserID(),true);
        }catch (Exception ee) {
            ee.printStackTrace();
        }
    }

    /**
     * 检查当前用户在该groupID组中是否存在群禁言,若存在，会收到GroupBan4User的消息
     * */
    public void checkGroupBan4CurrentUser(String groupID)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        this.engine.sendMessage(null, ContractType.CheckGroupBan4CurrentUser.getType(), null, groupID,false);
    }

    /**
     * 获取群组中所有正在禁言的记录
     * */
    public List<GroupBan> getGroupBans4Group(String groupID) {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return null;
        }
        try {
            byte[] info = this.engine.getCustomizeOutter().query(ContractType.GetGroupBans4Group.getType(), groupID.getBytes(StandardCharsets.UTF_8));
            List<GroupBan> groupBans = GroupBan.deserializeGroupBanList(info);
            return groupBans;
        } catch (Exception ee) {
            ee.printStackTrace();
            return null;
        }
    }

    /**
     * 获取该组是否存在全局禁言
     * */
    public boolean existAllGroupBan(String groupID)
    {
//        if (!this.engine.connected()) {
//            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
//            return false;
//        }
//        try {
//            byte[] info = this.engine.getCustomizeOutter().query(ContractType.ExistAllGroupBan.getType(), groupID.getBytes("utf-8"));
//            ByteBuf buffer = SerializeHelper.wrappedBuffer(info);
//            return buffer.readBoolean();
//        }catch (Exception ee) {
//            ee.printStackTrace();
//            return false;
//        }
        return false;
    }

    /**
     * 开启群组全员全员禁言（管理员、创始人除外）
     * */
    public void setAllGroupBan(String groupID)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        this.engine.sendMessage(null, ContractType.GroupBan4Group.getType(), null, groupID,true);
    }

    /**
     * 关闭群组全员禁言
     * */
    public void removeAllGroupBan(String groupID)
    {
        if (!this.engine.connected()) {
            ToastUtils.showShort(this.mContext, this.mContext.getString(R.string.offlineTips));
            return;
        }
        this.engine.sendMessage(null, ContractType.RemoveGroupBan4Group.getType(), null, groupID,true);
    }
    //endregion


    //region PostChatEvent4RichChatMessageReceived
    /**
     * 將PC端的多張圖片消息分成多條消息顯示
     * @param groupID 组id（如果不是组消息，sourceID）接收者ID
     * @param clientType 发送方的客户端类型
     * @param sourceID 发送者ID
     * @param richChatMessage 消息内容
     * @param isGroupChat 是否为群消息
     * */
    public void postChatEvent4RichChatMessageReceived(String groupID, ClientType clientType, String sourceID, RichChatMessage richChatMessage, boolean isGroupChat)
    {
        this.postChatEvent4RichChatMessageReceived(groupID,clientType,sourceID,richChatMessage,isGroupChat,false,"","");
    }


    /**
     * 將PC端的多張圖片消息分成多條消息顯示
     * @param groupID 组id（如果不是组消息，sourceID）接收者ID
     * @param clientType 发送方的客户端类型
     * @param sourceID 发送者ID
     * @param richChatMessage 消息内容
     * @param isGroupChat 是否为群消息
     * @param isEcho 是否为回声
     * @param atMemberIDs 消息@的对象ID 集合（英文逗号','分隔）
     * @param snapchatMessageID 阅后即焚消息ID
     * */
    public void postChatEvent4RichChatMessageReceived(String groupID, ClientType clientType, String sourceID, RichChatMessage richChatMessage, boolean isGroupChat, boolean isEcho,String atMemberIDs,String snapchatMessageID)
    {
        if(richChatMessage==null)
        {
            return;
        }
        try
        {
            if (richChatMessage.getNonTextHashMap() != null && richChatMessage.getNonTextHashMap().size() > 0)
            {
                Iterator<Map.Entry<Integer, NonText>> it = richChatMessage.getNonTextHashMap().entrySet().iterator();
                while (it.hasNext()){
                    Map.Entry<Integer, NonText> entry=it.next();
                    Integer key= entry.getKey();
                    NonText value=entry.getValue();
                    if (value.getChatBoxElementType() == ChatBoxElemnetType.Image)
                    {
                        RichChatMessage chatContent = new RichChatMessage();
                        chatContent.setText(" ");
                        NonText nonText = new NonText();
                        nonText.setChatBoxElementType(ChatBoxElemnetType.Image);
                        nonText.setImage(value.getImage());
                        chatContent.getNonTextHashMap().put(0, nonText);
                        ChatEvent chatEvent= new ChatEvent(groupID, clientType, sourceID, chatContent, isGroupChat);
                        chatEvent.isEcho=isEcho;
                        chatEvent.atMemberIDs=atMemberIDs;
                        chatEvent.snapchatMessageID=snapchatMessageID;
                        chatEvent.occurrenceTime=chatContent.TransferTime;
                        EventBus.getDefault().post(chatEvent);
                        it.remove();
                    }
                }
            }
            if(richChatMessage.getNonTextHashMap().size()>0|| !StringHelper.isNullOrEmpty(richChatMessage.getText()) )
            {
                if(richChatMessage.getText().equals(" ")&&richChatMessage.getNonTextHashMap().size()==0)//若只是一個佔位符則跳出
                {
                    return;
                }
                ChatEvent chatEvent= new ChatEvent(groupID, clientType, sourceID, richChatMessage, isGroupChat);
                chatEvent.isEcho=isEcho;
                chatEvent.atMemberIDs=atMemberIDs;
                chatEvent.snapchatMessageID=snapchatMessageID;
                chatEvent.occurrenceTime=richChatMessage.TransferTime;
                EventBus.getDefault().post(chatEvent);
                Log.d("收到消息",chatEvent.msg.getText());
            }
        }catch (Exception ex)
        {
            ex.printStackTrace();
        }

    }
    //endregion

}
